package org.jeecg.config.mybatis;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.oConvertUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

/**
 * 单数据源配置（jeecg.datasource.open = false时生效）
 * @Author zhoujf
 *
 */
@Configuration
@MapperScan(value={"org.jeecg.modules.**.mapper*","cn.aresoft.**.mapper.**"})
@Slf4j
public class MybatisPlusSaasConfig {
    /**
     * tenant_id 字段名
     */
    private static final String TENANT_FIELD_NAME = "company_code";
    /**
     * 哪些表需要做多租户 表需要添加一个字段 tenant_id
     */
    private static final List<String> TENANT_TABLE = new ArrayList<String>();

    static {
        TENANT_TABLE.add("locationa");
        TENANT_TABLE.add("locationb");
        TENANT_TABLE.add("locationc");
        TENANT_TABLE.add("locationa_type");

        TENANT_TABLE.add("unit");//单位
        TENANT_TABLE.add("direction");//描述方位
        TENANT_TABLE.add("type_for_reporting");//计算类别
        TENANT_TABLE.add("component_type");//组件类型
        TENANT_TABLE.add("sub_type");//组件子类型
        TENANT_TABLE.add("manufacturers");//生产厂家
        TENANT_TABLE.add("service_type");//介质状态
        TENANT_TABLE.add("service_type_report");
        TENANT_TABLE.add("chemical");//化学品
        TENANT_TABLE.add("base_chemical");//化学品基础
        TENANT_TABLE.add("product_stream");//产品流
        TENANT_TABLE.add("product_stream_percentage");//产品流化学品

        TENANT_TABLE.add("frequency");//检测频率
        TENANT_TABLE.add("instrument");//检测仪器
        TENANT_TABLE.add("calibration_threshold");//标准气理论浓度
        TENANT_TABLE.add("cylinder");//标准气
        TENANT_TABLE.add("leak_source");//泄露源
        TENANT_TABLE.add("repair");//维修措施
        TENANT_TABLE.add("repair_type");//维修措施
        TENANT_TABLE.add("minimum_testing_time");//最小检测时间
        TENANT_TABLE.add("minimum_testing_time_detail");//最小检测时间详情
        TENANT_TABLE.add("formula_set"); //排放公式
        TENANT_TABLE.add("formula");
        TENANT_TABLE.add("calibration");
        TENANT_TABLE.add("daily_calibration");//日常校准
        TENANT_TABLE.add("drift_calibration");//漂移校准

        TENANT_TABLE.add("change_reason");//组件更改原因
        TENANT_TABLE.add("dtm");//难于检测原因
        TENANT_TABLE.add("utm");//险于检测原因
        TENANT_TABLE.add("removal_reason");//暂时移除原因
        TENANT_TABLE.add("poos_reason");//永久移除原因
        TENANT_TABLE.add("dor");
        TENANT_TABLE.add("dor_reason");//延迟维修原因
        TENANT_TABLE.add("no_repair_reason");//无需维修原因
        TENANT_TABLE.add("manual_barcode_reason");//手动输入条形码原因

        TENANT_TABLE.add("rule");//法规
        TENANT_TABLE.add("rule_section");//法规详情
        TENANT_TABLE.add("rule_assignment");//法规分配
        TENANT_TABLE.add("rule_changelog");//法规操作历史
        TENANT_TABLE.add("rule_section_instru_threshold");
        TENANT_TABLE.add("rule_section_aov_threshold");
        TENANT_TABLE.add("rule_inspection_chain");
        TENANT_TABLE.add("inspection");
        TENANT_TABLE.add("component");
        TENANT_TABLE.add("documents");//文档资料
        TENANT_TABLE.add("image");
        TENANT_TABLE.add("oel");//开口管线

        TENANT_TABLE.add("component_batch_history");
        TENANT_TABLE.add("component_document");
        TENANT_TABLE.add("locationc_batch_history");
        TENANT_TABLE.add("rule_check");
        TENANT_TABLE.add("inspection_task");//分配任务
        TENANT_TABLE.add("weather_parameter");//分配任务
        TENANT_TABLE.add("approval_dor_component");//
        TENANT_TABLE.add("removal_component");//
        TENANT_TABLE.add("removal");//
        TENANT_TABLE.add("approval_dor");//
        TENANT_TABLE.add("inspection_download");
        TENANT_TABLE.add("inspection_task_detail");//
        TENANT_TABLE.add("inspection_batch_history");
        TENANT_TABLE.add("data_entry_template");
        TENANT_TABLE.add("data_entry_template_field");
        TENANT_TABLE.add("data_entry_template_data");
//        //角色、菜单、部门
//        tenantTable.add("sys_role");
//        tenantTable.add("sys_permission");
        TENANT_TABLE.add("dept_info");
        TENANT_TABLE.add("filter");
    }


    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public Expression getTenantId() {
                String tenantId = oConvertUtils.getString(TenantContext.getTenant(),"LK");
                return new LongValue("'"+tenantId+"'");
            }

            @Override
            public String getTenantIdColumn(){
                return TENANT_FIELD_NAME;
            }

            // 返回 true 表示不走租户逻辑
            @Override
            public boolean ignoreTable(String tableName) {
                for(String temp: TENANT_TABLE){
                    if(temp.equalsIgnoreCase(tableName)){
                        return false;
                    }
                }
                return true;
            }
        }));
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //update-begin-author:zyf date:20220425 for:【VUEN-606】注入动态表名适配拦截器解决多表名问题
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor());
        //update-end-author:zyf date:20220425 for:【VUEN-606】注入动态表名适配拦截器解决多表名问题
        return interceptor;
    }

    /**
     * 动态表名切换拦截器,用于适配vue2和vue3同一个表有多个的情况,如sys_role_index在vue3情况下表名为sys_role_index_v3
     * @return
     */
    private DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            //获取需要动态解析的表名
            String dynamicTableName = ThreadLocalDataHelper.get(CommonConstant.DYNAMIC_TABLE_NAME);
            //当dynamicTableName不为空时才走动态表名处理逻辑,否则返回原始表名
            if (ObjectUtil.isNotEmpty(dynamicTableName) && dynamicTableName.equals(tableName)) {
                // 获取前端传递的版本号标识
                Object version = ThreadLocalDataHelper.get(CommonConstant.VERSION);
                if (ObjectUtil.isNotEmpty(version)) {
                    //拼接表名规则(原始表名+下划线+前端传递的版本号)
                    return tableName + "_" + version;
                }
            }
            return tableName;
        });
        return dynamicTableNameInnerInterceptor;
    }

//    /**
//     * 下个版本会删除，现在为了避免缓存出现问题不得不配置
//     * @return
//     */
//    @Bean
//    public ConfigurationCustomizer configurationCustomizer() {
//        return configuration -> configuration.setUseDeprecatedExecutor(false);
//    }
//    /**
//     * mybatis-plus SQL执行效率插件【生产环境可以关闭】
//     */
//    @Bean
//    public PerformanceInterceptor performanceInterceptor() {
//        return new PerformanceInterceptor();
//    }

}
